#include "Syp/SypEngine.h"

bool runGame = true;
Syp::Button* walkBtn;
Syp::Button* idleBtn;

void onClose()
{
	runGame = false;
}

void mouseOver(Syp::GuiBase* g)
{
	g->setUVCoord(0.5f, 0, 0.5f, 0.71875f);
}

void mouseOut(Syp::GuiBase* g)
{
		g->setUVCoord(0,0,0.5f,0.71875f);
}


void mouseDown(Syp::GuiBase* g )
{
    Syp::Color3f c( 0.5f,0.5f,0.5f );
	g->setColor( c );
}

void mouseUp( Syp::GuiBase* g )
{
    Syp::Color3f c( 1,1,1 ) ;
	g->setColor( c );
}


int main()
{
	//Create the Engine
	Syp::SypEngine::createSypEngine();
	//Now we retrieve a reference of it
	Syp::SypEngine& g = Syp::SypEngine::getSypEngine();
	//Initialise it for resolution 1024 X 768, false specifies we do not want fullscreen
	g.init("GPU Skinning Demo",800,600,false);
	g.setWindowCloseCallback(onClose);

	Syp::AngleAxis a;
	a.w = 90.0f;
	a.x = 1.0f;
	a = a.convertToQuat();
	a = a.convertToAngleAxis();

	//Our reference of the SceneManager
	Syp::SceneManager& SM = Syp::SceneManager::getSceneManager();
	//We need to assign a default camera
	Syp::Camera* myCam = Syp::Camera::createCamera();
	//myCam->rotateAroundLocalAxis(Syp::AngleAxis(1.0f,0,0,90.0f));
	myCam->setPosition(0,0, 100,1);
	//And tell the scene to use it
	SM.setActiveCamera(myCam);

	Syp::Light* l = new Syp::Light();
	l->setPosition(0.0f,0,1,0);
	SM.addLight(l);


	Syp::IndexedMesh* mob;
	mob = Syp::IndexedMesh::loadFromFile("Model/monster-mesh.sypm");
	Syp::Skeleton* mySkele = Syp::Skeleton::createSkeleton("Model/monster-mesh.syps");
	mySkele->loadFromFile("Model/monster-mesh.syps");
	mob->useSkeleton(mySkele);

	Syp::AnimSet as;
	as.name = "WalkCycle";
	as.start = 0.033333f;
	as.end = 1.33333f;
	mySkele->addAnimSet(as);
	as.name = "WaveCycle";
	as.start = 1.36667f;
	as.end = 4.0f;
	mySkele->addAnimSet(as);

	Syp::MeshInstance* mobI;
	for(int i =0; i < 5; ++i)
	{
		for(int j=0; j < 5; ++j)
		{
			mobI = Syp::MeshInstance::createMeshInstance();
			mobI->setPosition(200.0f * i - 400.0f,100.0f * j - 300.0f,-100.0f * j -800.0f );
			//mobI->setPosition(0,0, -500.0f );
			mobI->rotateAroundLocalAxis(Syp::AngleAxis(1.0f,0,0,-90.0f));
			mobI->speed = (rand()%3) * i + 1;
			mobI->AnimTime = 0.1f * j;
			mobI->useMesh(mob);
			mobI->animate = true;
			mobI->currAnimSet = j%2;
		}
	}

	//GPUSkinning Test
	Syp::MeshInstance* skinType;
	if( Syp::PassRegistry::getRegistry().getEntry("GPUSkinning")->runnableOnHardware() )
	{
		skinType = Syp::SypEngine::getSypEngine().getSysFontRef().generateStaticMesh("GPU Skinning", 600.0f, 555.0f, 999.0f);
	}
	else
	{
		skinType = Syp::SypEngine::getSypEngine().getSysFontRef().generateStaticMesh("CPU Skinning", 600.0f, 555.0f, 999.0f);
	}

	////////GUI//////////

 //   Syp::Color3f c(0.8f,0.8f,0.8f);

	//Syp::Frame* cPanel = Syp::Frame::createFrame("/c(1 1 1) Control Panel",300.0f,100.0f);
	//cPanel->getMIRef().setPosition(300.0f,350.0f,0);

	//cPanel->setColor( c );
	//c.r = 0;
	//c.g = 0;
	//c.b = 0.8f;
	//cPanel->setTitleBarColor( c );

 //   //Left Button
	//walkBtn = Syp::Button::createButton("Walk", 64.0f, 23.0f);
	//walkBtn->useTexture("Textures/btn.png");
	//walkBtn->setUVCoord(0,0,0.5f,0.71875f);
	//walkBtn->getLabel()->setText("/c(0 0 0)Walk");
	//walkBtn->getMIRef().bindToNode( &cPanel->getMIRef() );
	//walkBtn->getMIRef().setPosition(320.0f,380.0f,1.0f);

	//walkBtn->getLabel()->getMIRef().offsetPosition(15.0f,1.0f,1.0f);
	////walkBtn->setColor( Syp::Color3f(0,0,1.0f) );
	//walkBtn->onMouseOver.connect(&mouseOver);
	//walkBtn->onMouseOut.connect(&mouseOut);
	//walkBtn->onMouseLeftDown.connect( &mouseDown );
	//walkBtn->onMouseLeftUp.connect( &mouseUp );

	/////////////////
	

	//im.subscribeToMouseUpdates( boost::bind(&Syp::Frame::recieveMouseInfo, cPanel, _1,_2) );
	//im.subscribeToMouseUpdates( boost::bind(&Syp::Button::recieveMouseInfo, walkBtn, _1,_2) );
	
	Syp::InputManager& im = Syp::InputManager::getInputManager();
	
	do
	{//Keep updating/drawing screen as long as window is open

		SM.beginDrawing();
		g.run();
		
		//myCam->rotateAroundOrigin( Syp::AngleAxis(0,0,1, 0.5f));

		if(im.getMouseStateRef().mouseLeft)
		{
			int diff = im.getMouseStateRef().mouseX - im.getMouseStateRef().lastMouseX;
			int diffY = im.getMouseStateRef().mouseY - im.getMouseStateRef().lastMouseY;
			
			
			myCam->rotateAroundLocalAxis( Syp::AngleAxis(1,0,0,-diffY) );
			myCam->rotateAroundWorldAxis( Syp::AngleAxis(0,1,0,diff));
			
			//myCam->rotateAroundLocalAxis( Syp::AngleAxis(0,1,0,-diff) );			

		}
		int k = im.getKey().key;
		
		if(k == SYP_KEY_END)
		{
			float id[16];
			Syp::Math::IdentityMatrix(id);
			myCam->setMatrix(id);
		}
		else if(k == SYP_KEY_LEFT)
		{
			myCam->rotateAroundWorldAxis( Syp::AngleAxis(0,1,0,2.0f) );
		}
		else if(k == SYP_KEY_RIGHT)
		{
			myCam->rotateAroundWorldAxis( Syp::AngleAxis(0,1,0,-2.0f) );
		}
		else if(k == SYP_KEY_UP)
		{
			myCam->rotateAroundLocalAxis( Syp::AngleAxis(1,0,0,2.0f) );
		}
		else if(k == SYP_KEY_DOWN)
		{
			myCam->rotateAroundLocalAxis( Syp::AngleAxis(1,0,0,-2.0f) );
		}
		else if(k == SYP_KEY_ESC)
		{
			runGame = false;
		}
		
		SM.endDrawing();
	}while(runGame);


	//Delte Cameras because they are not resources and in turn not managed by the engine
	Syp::Camera::destroyCamera(myCam);

	Syp::SypEngine::releaseSypEngine();

	return 0;
}






//#include "Syp/SypEngine.h"
//#ifdef CHECKMEM
//#include "mmgr.h"
//#endif
//using namespace Syp;
//
//bool mouseLook = false;
//
//void mouseClick(GuiBase* g)
//{
//	if(GuiBase::getMouseFocus() == g)
//	{
//		if(!mouseLook)
//		{
//			g->setUVCoord(0.5f,0.0f,0.5f,0.625f);
//			mouseLook = true;
//		}
//		else
//		{
//			g->setUVCoord(0.0f,0.0f,0.5f,0.625f);
//			mouseLook = false;
//		}
//	}
//}
//
//
//int main()
//{
//	//boost::signal<void (GuiBase* g)> test;
//	//test.connect(&mouseClick);
//	//test(0);
//	bool runGame = true;
//
//	SypEngine::createSypEngine();
//	SypEngine& g = SypEngine::getSypEngine();
//	g.init("Syp Engine Demo",1280,800,false);
//
//	//Test PassRegistry
//	PassRegistry::getRegistry().dumpInfo();
//	EffectRegistry::getRegistry().dumpInfo();
//
//	//VertexShader* sh = new VertexShader();
//	//sh->loadShaderFromFile("gliLog.txt");
//	//sh->compileShader();
//
//	SceneManager& SM = SceneManager::getSceneManager();
//
//	Font* txt = Font::createFont("MagicalMystery");
//	txt->initFonts("Fonts/MagicalMystery.ttf",18);
//	txt->generateStaticMesh("/c(1 1 1)This is the /c(1 0 0)Font /c(1 1 1)Demo.", 200,300,999.0f);
//
//	Camera* myCam = Camera::createCamera();
//
//	//myCam->loadCameraFromFile("camera.txt");
//	//myCam->setPosition(0.0f,200.0f,650.0f);
//	myCam->setPosition(0.0f,8.0f,80.0f);
//	SM.setActiveCamera(myCam);
//
//	Syp::Sprite* background = Syp::Sprite::createSprite("Materials/background.mat",0,512,512);
//
//	MeshInstance* bg = MeshInstance::createMeshInstance();
//	//m->rotateAroundLocalAxis(0,-90.0f);
//	//m->speed = 0.1f * i;
//	//m->AnimTime = 0.1f * j;
//	bg->useMesh(background);
//	bg->mode = Syp::RenderMode::ORTHO;
//	//m->currAnimSet = 0;
//
//	Light* l = new Light();
//	l->setPosition(0.0f,0,1,0);
//
//	//l->ambient[0] = l->ambient[1] = l->ambient[2] = l->ambient[3] = 1.0f;
//	SM.addLight(l);
//	//	SM.addLight(l2);
//
//	//IndexedMesh* box = IndexedMesh::loadFromFile("Model/wat2");
//	//IndexedMesh* ground = IndexedMesh::loadFromFile("Model/ground");
//	//box->writeToFile("test.sypm");
//	//IndexedMesh* testMesh = IndexedMesh::loadFromFile("Model/shop.sypm");
//	IndexedMesh* testMesh = IndexedMesh::loadFromFile("Model/monster-mesh.sypm");
//	Skeleton* mySkele = Skeleton::createSkeleton("Model/wolf-mesh.syps");
//	mySkele->loadFromFile("Model/monster-mesh.syps");
//	testMesh->useSkeleton(mySkele);
//
//	AnimSet as;
//	as.name = "WalkCycle";
//	as.start = 0.033333f;
//	as.end = 1.33333f;
//	mySkele->addAnimSet(as);
//
//
//
//	//testMesh->setRenderingFormat(FORMAT_POINTS);
//
//	//	MeshInstance* m2 = MeshInstance::createMeshInstance();
//	MeshInstance* m;
//	//m2->useMesh(origMesh);
//	//	Instances to place the meshes
//
//	for(int i=0;i<10;++i)
//	{
//		for(int j=0;j<10;++j)
//		{
//			m = MeshInstance::createMeshInstance();
//			m->setPosition(100.0f * i - 500.0f,100.0f * j,-800.0f);
//			m->rotateAroundLocalAxis(0,-90.0f);
//			//m->speed = 0.1f * i;
//			m->AnimTime = 0.1f * j;
//		//	m->useMesh(testMesh);
//			m->currAnimSet = 0;
//
//			m->animate = true;
//		}
//
//		//m->getMaterial()->subMaterials[0].useEffect("ShaderFF");
//		/*	Material* mod = new Material(*m->getMaterial());
//		mod->subMaterials[0].lit = false;
//		m->useMaterial(mod);
//		mod->subMaterials[0].diffuse[2] = 0.0f;*/
//	}
//
//	IndexedMesh* terrainMesh = IndexedMesh::loadFromFile("Model/terrain-mesh.sypm");
//
//	MeshInstance* terrain = MeshInstance::createMeshInstance();
//	//terrain->useMesh(terrainMesh);
//	terrain->rotateAroundLocalAxis(0,-90.0f);
//	terrain->setPosition(0.0f,-50.0f,-500.0f);
//
//	InputManager& im = InputManager::getInputManager();
//	int keyPressed = 0;
//
//	MeshInstance* sypEng = SypEngine::getSypEngine().getSysFontRef().generateStaticMesh("Syp Engine 0.14 Demo", 10.0f,10.0f,999.0f);
//	MeshInstance* helpTxt = SypEngine::getSypEngine().getSysFontRef().generateStaticMesh("Keys available:\n/c(1 1 0)Del : Starts camera animation.\nArrow Keys : Moves light\nEsc : Closes application", 750.0f,750.0f,999.0f);
//	MeshInstance* skinType;
//	if( Syp::PassRegistry::getRegistry().getEntry("GPUSkinning")->runnableOnHardware() )
//	{
//		skinType = SypEngine::getSypEngine().getSysFontRef().generateStaticMesh("GPU Skinning", 750.0f, 675.0f, 999.0f);
//	}
//	else
//	{
//		skinType = SypEngine::getSypEngine().getSysFontRef().generateStaticMesh("CPU Skinning", 750.0f, 675.0f, 999.0f);
//	}
//
//	Frame* myFrame = Frame::createFrame("My Frame",512.0f,256.0f);
//	myFrame->getMIRef().setPosition(100.0f,100.0f,49.0f);
//	myFrame->getTitle()->setTextFont(&SypEngine::getSypEngine().getSysFontRef());
//	myFrame->getTitle()->setText("/c(0 0 0) Control Panel");
//	//myFrame->useTexture("Textures/frame.jpg");
//
//	Button* myButton = Button::createButton("myButton",64.0f,20.0f);
//	myButton->useTexture("Textures/Newbtn.png");
//	myButton->getLabel()->setText("/c(0 0 0)Left");
//	myButton->getLabel()->getMIRef().offsetPosition(20.0f,1.0f,1.0f);
//	myButton->getLabel()->getMIRef().bindToNode( &myButton->getMIRef() );
//	myButton->setUVCoord(0.0f,0.0f,0.5f,0.625f);
//	myButton->getMIRef().setPosition(200.0f,200.0f,50.0f);
//	myButton->onMouseLeftUp.connect(&mouseClick);
//
//	myButton->getMIRef().bindToNode(&myFrame->getMIRef());
//
//	////We subscribe to mouse updates,        (function to recieve update, object)
//	im.subscribeToMouseUpdates(boost::bind(&Button::recieveMouseInfo, myButton, _1,_2));
//	im.subscribeToMouseUpdates(boost::bind(&Frame::recieveMouseInfo, myFrame, _1,_2));
//	SceneManager::getSceneManager().dumpRenderQue();
//
//	ResourceManager::getResourceManager().dumpResourceInfo();
//	FontRegistry::getRegistry().dumpInfo();
//	//myCam->animate = true;
//
//
//
//	do
//	{
//		SM.beginDrawing();
//		g.run();
//		KeyEvent k = im.getKey();
//		Quat view;
//		view.z = -1.0f;
//		view.w = 0.0f;
//		Quat cam = myCam->getOrientation();
//		Quat camI = cam;
//		Math::InverseQuat(camI);
//		Quat res = cam * view * camI;
//		res = res * 5.0f;
//		if(mouseLook)
//		{
//			const MouseState& ms = im.getMouseStateRef();
//			float xRot = (ms.mouseX - ms.lastMouseX)/10.0f;
//			float yRot = (ms.mouseY - ms.lastMouseY)/10.0f;
//
//			myCam->rotateAroundLocalAxis(1,xRot);
//			myCam->rotateAroundWorldAxis(0,-yRot);
//
//		}
//		switch(k.key)
//		{
//		case SYP_KEY_ESC:
//			runGame = false;
//			break;
//		case SYP_KEY_LEFT:
//			myCam->offsetPosition(-1.0f,0,0);
//			break;
//		case SYP_KEY_RIGHT:
//			myCam->offsetPosition(1.0f,0,0);
//			break;
//		case SYP_KEY_UP:
//			myCam->offsetPosition(-res.x,-res.y,res.z);
//			break;
//		case SYP_KEY_DOWN:
//			myCam->offsetPosition(res.x,res.y,-res.z);
//			break;
//		case SYP_KEY_DEL:
//			if(k.state == 1)
//				myCam->setAnimation( !myCam->isAnimated() );
//			break;
//		}
//
//		//myCam->getOrientation().Normalize();
//		//m->rotateAroundLocalAxis(1,1.0f);
//		SM.endDrawing();
//	}while(runGame && g.windowIsOpen());
//
//	//Delte Cameras because they are not resources and in turn not managed by the engine
//	Camera::destroyCamera(myCam);
//	GuiBase::destroyGuiComponent(myButton);
//	GuiBase::destroyGuiComponent(myFrame);
//
//	delete l;
//	ResourceManager::getResourceManager().cleanUp();
//	SypEngine::releaseSypEngine();
//
//
//	return 0;
//}
